package com.yunxin.core.application.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.Method;
import cn.hutool.json.JSONObject;
import com.yunxin.common.exception.BusinessException;
import com.yunxin.common.result.ResultCode;
import com.yunxin.common.utils.SnowflakeKeyGenerator;
import com.yunxin.core.application.assembler.MerchantAssembler;
import com.yunxin.core.application.command.merchant.*;
import com.yunxin.core.application.service.MerchantApplicationAdminService;
import com.yunxin.core.domain.external.merchant.MerchantExternalService;
import com.yunxin.core.domain.model.contact.ContactMessageSendTaskDetail;
import com.yunxin.core.domain.model.contact.ContactMessageSendTaskDetailRepository;
import com.yunxin.core.domain.model.contact.ContactMessageTemplateRepository;
import com.yunxin.core.domain.model.merchant.*;
import com.yunxin.core.domain.service.merchant.MerchantService;
import com.yunxin.core.infra.common.contact.enums.PassiveTriggerEnum;
import com.yunxin.core.infra.persistence.mapper.user.SysUserCoreMapper;
import com.yunxin.core.utils.infra.common.constant.CoreResultCode;
import com.yunxin.core.utils.infra.common.constant.ServerResultCode;
import com.yunxin.core.utils.infra.common.enums.KeyGeneratorPrefixEnum;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author zero°
 * @since 2023-05-26
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class MerchantApplicationAdminServiceImpl implements MerchantApplicationAdminService {

    private final MerchantInfoRepository merchantInfoRepository;

    private final MerchantUserAccountRepository merchantUserAccountRepository;

    private final MerchantService merchantService;

    private final MerchantAssembler merchantAssembler;

    private final SnowflakeKeyGenerator sequenceGenerator;


    @Value("${sms.gateway.url}")
    private String url;

    @Value("${sms.gateway.code}")
    private String code;

    @Value("${sms.gateway.key}")
    private String key;

    @Value("${sms.gateway.secret}")
    private String secret;

    @Autowired
    private ContactMessageTemplateRepository messageTemplateRepository;

    @Autowired
    private ContactMessageSendTaskDetailRepository messageSendTaskDetailRepository;

    private final MerchantExternalService merchantExternalService;

    private final SysUserCoreMapper sysUserCoreMapper;


    @Override
    public boolean addMerchant(AddMerchantCommand request) {
        MerchantInfo merchantInfo = merchantAssembler.fromAddMerchantCommand(request);
        merchantInfo.setMerchantCode(sequenceGenerator.generateKey(KeyGeneratorPrefixEnum.MERCHANT.getPrefix()));
        merchantInfo.setEditor(request.getCreator());
        MerchantContactPerson merchantContactPerson = merchantAssembler.fromMerchantContactPersonCommand(request.getMerchantContactPerson());
        merchantContactPerson.setCreator(request.getCreator());
        merchantContactPerson.setEditor(request.getCreator());
        MerchantInvoiceInfo merchantInvoiceInfo = merchantAssembler.fromMerchantInvoiceCommand(request.getMerchantInvoice());
        merchantInvoiceInfo.setCreator(request.getCreator());
        merchantInvoiceInfo.setEditor(request.getCreator());
        return merchantService.addMerchantData(merchantInfo, merchantContactPerson, merchantInvoiceInfo);
    }

    @Override
    public boolean updateMerchant(UpdateMerchantCommand command) {
        MerchantInfo oldMerchantInfo = merchantInfoRepository.getMerchantInfoById(command.getId());
        if (Objects.isNull(oldMerchantInfo)) {
            throw new BusinessException(ResultCode.DATA_NO_EXIST_ERROR);
        }
        MerchantInfo merchantInfo = merchantAssembler.fromUpdateMerchantCommand(command);
        merchantInfo.setMerchantCode(oldMerchantInfo.getMerchantCode());
        merchantInfo.setVersion(oldMerchantInfo.getVersion() + 1);
        MerchantContactPerson merchantContactPerson = merchantAssembler.fromMerchantContactPersonCommand(command.getMerchantContactPerson());
        merchantContactPerson.setMerchantId(oldMerchantInfo.getId());
        merchantContactPerson.setCreator(command.getEditor());
        merchantContactPerson.setEditor(command.getEditor());
        MerchantInvoiceInfo merchantInvoiceInfo = merchantAssembler.fromMerchantInvoiceCommand(command.getMerchantInvoice());
        merchantInvoiceInfo.setMerchantId(oldMerchantInfo.getId());
        merchantInvoiceInfo.setCreator(command.getEditor());
        merchantInvoiceInfo.setEditor(command.getEditor());
        return merchantService.updateMerchantData(merchantInfo, merchantContactPerson, merchantInvoiceInfo);
    }

    @Override
    public boolean updateMerchantStatus(UpdateMerchantStatusCommand command) {
        MerchantInfo oldMerchantInfo = merchantInfoRepository.getMerchantInfoById(command.getId());
        if (Objects.isNull(oldMerchantInfo)) {
            throw new BusinessException(ResultCode.DATA_NO_EXIST_ERROR);
        }
        if (oldMerchantInfo.getMerchantStatus().equals(command.getMerchantStatus())) {
            throw new BusinessException(ServerResultCode.MERCHANT_STATUS_ERROR);
        }
        return merchantService.updateMerchantStatus(oldMerchantInfo, command.getMerchantStatus(), command.getEditor());
    }

    @Override
    public boolean operateMerchantUserAccount(OperateMerchantUserAccountCommand request) {
        MerchantUserAccount merchantUserAccount = merchantUserAccountRepository.getMerchantUserAccountBySysUserId(request.getSysUserId());
        boolean result;
        if (Objects.isNull(merchantUserAccount)) {
            merchantUserAccount = new MerchantUserAccount();
            merchantUserAccount.setSysUserId(request.getSysUserId());
            merchantUserAccount.setAccountName(request.getAccountName());
            merchantUserAccount.setAccountPhone(request.getAccountPhone());
            merchantUserAccount.setAccountStatus(request.getAccountStatus());
            merchantUserAccount.setRemark(request.getRemark());
            // 说明是由商户账户创建的 创建商户账户的场景
            // 1.管理后台用户管理，关联商户时创建，默认为父id为0（即父账号）
            // 2.管理后台商户用户管理创建，默认父id为操作用户id（即子账号）
            // 子账号不可创建即操作商户账户 由管理后台用户角色控制资源，这里做强校验(只有商户管理员-父账号可以创建)
            if (Objects.nonNull(request.getOperateSysUserId())) {
                MerchantUserAccount parent = merchantUserAccountRepository.getMerchantUserAccountBySysUserId(request.getOperateSysUserId());
                if (!ObjectUtils.isEmpty(parent) && parent.getParentId() > 0) {
                    throw new BusinessException(CoreResultCode.MERCHANT_ACCOUNT_LEVEL_EXIST);
                }
                merchantUserAccount.setParentId(parent.getId());
                merchantUserAccount.setMerchantId(parent.getMerchantId());
            } else {
                merchantUserAccount.setParentId(0L);
                merchantUserAccount.setMerchantId(request.getMerchantId());
            }
            merchantUserAccount.setCreator(request.getOperator());
            merchantUserAccount.setEditor(request.getOperator());
            result = merchantUserAccountRepository.saveMerchantAccount(merchantUserAccount);
        } else {
            MerchantUserAccount updateMerchantUserAccount = getMerchantUserAccount(request, merchantUserAccount);
            result = merchantUserAccountRepository.updateMerchantAccount(updateMerchantUserAccount);
        }
        return result;
    }


    @Override
    public boolean operateMerchantAccountStatus(OperateMerchantAccountStatusCommand request) {
        MerchantUserAccount merchantUserAccount = merchantUserAccountRepository.getMerchantUserAccountBySysUserId(request.getSysUserId());
        if (Objects.isNull(merchantUserAccount)) {
            throw new BusinessException(ResultCode.DATA_NO_EXIST_ERROR);
        }
        merchantUserAccount.setAccountStatus(request.getAccountStatus());
        merchantUserAccount.setVersion(merchantUserAccount.getVersion() + 1);
        merchantUserAccount.setEditor(request.getOperator());
        merchantUserAccount.setEditTime(new Date());
        return merchantUserAccountRepository.updateMerchantAccount(merchantUserAccount);
    }

    @Override
    public boolean operateMerchantAccountReceivingStatus(OperateMerchantAccountReceivingStatusCommand request,Long merchantId) {
        MerchantUserAccount merchantUserAccount = merchantUserAccountRepository.getMerchantUserAccountBySysUserId(request.getSysUserId());
        if (Objects.isNull(merchantUserAccount)) {
            throw new BusinessException(ResultCode.DATA_NO_EXIST_ERROR);
        }
        merchantUserAccount.setReceivingStatus(request.getReceivingStatus());
        merchantUserAccount.setEditor(request.getOperator());
        merchantUserAccount.setEditTime(new Date());
        merchantUserAccount.setVersion(merchantUserAccount.getVersion() + 1);
        boolean b = merchantUserAccountRepository.updateMerchantAccount(merchantUserAccount);
        // if (b && request.getReceivingStatus() == 0) {  // 修改成功就发短信且是关闭操作就发短信
        //     // 给对应客服和管理员发短信
        //     String userPhone = merchantExternalService.getAccountPhoneBySysUserId(request.getSysUserId());
        //     // 管理员电话
        //     List<String> adminPhones = sysUserCoreMapper.getAdminPhone(merchantId);
        //     String phone = String.join(",", adminPhones) + "," + userPhone;
        //     log.info("自营商户后台进量短信通知,客服电话：{},管理员电话：{}", userPhone, adminPhones);
        //     sendMsg(phone);

        // }
        return b;
    }

    @Override
    public boolean deleteMerchantAccount(List<Long> sysUserIds) {
        return merchantUserAccountRepository.deleteMerchantAccountBySysUserIds(sysUserIds);
    }


    /**
     * 获取更新 MerchantUserAccount
     * @param request request
     * @param merchantUserAccount merchantUserAccount
     * @return MerchantUserAccount
     */
    @NotNull
    private static MerchantUserAccount getMerchantUserAccount(OperateMerchantUserAccountCommand request, MerchantUserAccount merchantUserAccount) {
        MerchantUserAccount updateMerchantUserAccount = new MerchantUserAccount();
        updateMerchantUserAccount.setAccountName(request.getAccountName());
        updateMerchantUserAccount.setAccountStatus(request.getAccountStatus());
        updateMerchantUserAccount.setAccountPhone(request.getAccountPhone());
        updateMerchantUserAccount.setRemark(request.getRemark());
        updateMerchantUserAccount.setId(merchantUserAccount.getId());
        updateMerchantUserAccount.setVersion(merchantUserAccount.getVersion() + 1);
        updateMerchantUserAccount.setEditTime(new Date());
        updateMerchantUserAccount.setEditor(request.getOperator());
        return updateMerchantUserAccount;
    }


    private void sendMsg(String phones) {
        // 获取时间戳
        long timestamp = System.currentTimeMillis();
        // 生成签名
        String sign = key + secret + timestamp;
        // md5加密
        String md5Sign = SecureUtil.md5(sign).toLowerCase();

        List<ContactMessageSendTaskDetail> listTask = messageSendTaskDetailRepository.listMessageSendTaskDetailByTaskCode(PassiveTriggerEnum.ADMIN_USER_LOGIN_NOTIFY.getTaskCode());
        if (CollUtil.isNotEmpty(listTask)) {
            ContactMessageSendTaskDetail detail = listTask.get(0);
            // 短信内容
            var templateContent = messageTemplateRepository.getTemplateContentById(detail.getMessageTemplateId());
            HttpRequest request = HttpRequest.post(url + "/sms/batch/v1");

            // 添加参数
            JSONObject requestParam = new JSONObject();
            requestParam.put("appkey", key);
            requestParam.put("appcode", code);
            requestParam.put("sign", md5Sign);
            requestParam.put("phone", phones);
            requestParam.put("msg", templateContent);
            requestParam.put("timestamp", timestamp);

            // 设置请求方式
            request.method(Method.POST);
            // 传参方式
            request.contentType("application/json;charset=utf-8");
            // 添加参数
            request.body(requestParam.toString());
            // 发送请求
            HttpResponse response = null;
            try {
                response = request.execute();
            } catch (Exception e) {
                log.error("自营商户后台进量短信通知请求异常：", ExceptionUtil.stacktraceToString(e));
            }
            // 获取返回值
            String body = response.body();
            // 转json
            JSONObject jsonObject = new JSONObject(body);
            if (!Objects.equals(jsonObject.getStr("code"), "00000")) {
                log.error("自营商户后台进量短信通知异常,异常信息{}", jsonObject.getStr("desc"));
            }


        }
    }
}
